home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Archive / Graphics / QuickDraw GX / GX->PostScript Sample / GXToPostScript / Font Handler / OutputFontData.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  25.5 KB  |  852 lines  |  [TEXT/MPS ]

  1. /*
  2.      File:        OutputFontData.c
  3.  
  4.      Contains:    QuickDraw GX to PostScript conversion code.
  5.                          File contains functions which is responsible
  6.                         for outputting and encoding fonts at all levels of the 
  7.                         document.
  8.  
  9.      Version:    Technology:    Quickdraw GX 1.1.x
  10.       
  11.      Copyright:    © 1991-1997 by Apple Computer, Inc., all rights reserved.
  12. */
  13.  
  14. #include "GXToPSBuildConfig.h"
  15. #include "IOUtilities.h"
  16. #include <GXExceptions.h>
  17. #include "GXPrintingUniverse.h"
  18. #include "FontHandler.h"
  19. #include "FontHandlerPrivate.h"
  20. #include "FontHandlerVariations.h"
  21. #include <String.h>
  22. #include "FHResources.h"
  23.  
  24.  
  25. #ifdef resumeLabel
  26.     #undef resumeLabel
  27. #endif
  28. #define resumeLabel(exception)
  29.  
  30. #ifdef encodingsDontTakeFFFF
  31. /**********************
  32.     Temporary routine:  Remove in when works in TT (I hope q160).
  33.     
  34.     Sets all of the 0xffff entries in an encoding to be zero
  35.     
  36. ***********************/
  37. void ResetSentinalValues(unsigned short *encoding)
  38.     {
  39.         long        i;
  40.         for (i = 0; i < 256; ++i) {
  41.             if (encoding[i] == 0xFFFF)
  42.                 encoding[i] = 0;
  43.         }
  44.     }
  45. #endif
  46.  
  47. /********************************************
  48.  
  49.     Function: FontHandlerOutputVariationPSOperator
  50.     
  51.     This function calls GX to output the postscript font
  52.     variation operator for the font and style in question.
  53.     
  54. **********************************************/
  55. OSErr FontHandlerOutputVariationPSOperator(TFontHandlerContext context, gxStyle theStyle)
  56.     {
  57.         OSErr                                status;
  58.         long                                count;
  59.         gxFontVariation            *variations;
  60.         Handle                            h;
  61.         scalerStream                streamRecord;
  62.         
  63.         
  64.         /** Count the number of axes in the style vectoring through the font handler **/
  65.         
  66.         status = _FontHandlerGetStyleFontVariations(context, theStyle, &count, nil);
  67.         nrequire(status, failed_Count);
  68.     
  69.         if (count > 0) {
  70.         
  71.             /** Actually get the variations **/
  72.             
  73.             status = FHSetWorkHandleSize((TFontHandlerHdl)context, 
  74.                                                                         count * sizeof(gxFontVariation),
  75.                                                                         0, &h);
  76.             nrequire(status, failed_SetSize);
  77.             
  78.             HLockHi(h);
  79.             variations = (gxFontVariation*)*h;
  80.             
  81.             status = _FontHandlerGetStyleFontVariations(context, theStyle, &count, variations);
  82.             nrequire(status, failed_GetVariations);
  83.             
  84.             /** Now stream the variation PostScript operator **/
  85.             
  86.             streamRecord.types = (*(TFontHandlerHdl)context)->legalStreamTypes;
  87.             streamRecord.targetVersion = (*(TFontHandlerHdl)context)->productDescription;
  88.             streamRecord.action = variationPSOperatorStreamAction;
  89.             streamRecord.variationCount = count;
  90.             streamRecord.variations = variations;
  91.  
  92.             // DL 7/27/97:  This used to use the GX message, now we use the psDevice method.
  93.             status = (*(TFontHandlerHdl)context)->psDevice->StreamFont(FHgxGetStyleFont(theStyle), &streamRecord);
  94.             ncheck(status);
  95.             
  96.  
  97. failed_GetVariations:
  98.  
  99.             FHReleaseWorkspace((TFontHandlerHdl)context, 0);
  100.         
  101.         }//end if
  102.     
  103. failed_SetSize:
  104. failed_Count:
  105.  
  106.         return(status);
  107.         
  108.     }//FontHandlerOutputVariationPSOperator
  109.  
  110.  
  111.  
  112. //<FF>
  113. /********************************************
  114.  
  115.     Function: FHDownloadEncoding:
  116.     
  117.     Function streams an encoding for a printer resident
  118.     font based on the printer font record specified.  The encoding is
  119.     left on the operand stack.
  120.     
  121.     printerFont:                Pointer to The printer font record.
  122.     legalTypes:                    Legal types for streaming.
  123.     productDescription:    Product description string.
  124.  
  125. *********************************************/
  126. OSErr FHDownloadEncoding(CGXtoPostScriptDevice *psDevice, TPrinterFontRec *printerFont, scalerStreamTypeFlag legalTypes, char *productDescription);
  127. OSErr FHDownloadEncoding(CGXtoPostScriptDevice *psDevice, TPrinterFontRec *printerFont, scalerStreamTypeFlag legalTypes, char *productDescription)
  128.     {
  129.         OSErr                            status;
  130.         scalerStream            streamRecord;
  131.         unsigned long            *glyphBits;                    // Make copy of glyph bits because streaming can corrupt them.
  132.         
  133.         /** Copy the glyph usage data **/
  134.         
  135.         status = PrNewPtr((Ptr *) &glyphBits, printerFont->usageSize);
  136.         nrequire(status, failed_Alloc);
  137.         memcpy(glyphBits, printerFont->glyphUsage, printerFont->usageSize);
  138.         
  139. #ifdef encodingsDontTakeFFFF
  140.         ResetSentinalValues(printerFont->printerFontCodes);
  141. #endif
  142.  
  143.         streamRecord.types = legalTypes;
  144.         streamRecord.targetVersion = productDescription;
  145.         streamRecord.action = encodingOnlyStreamAction;
  146.         streamRecord.variationCount = 0;
  147.         streamRecord.variations = nil;
  148.         streamRecord.info.font.encoding = printerFont->printerFontCodes;
  149.         streamRecord.info.font.glyphBits = (long*)glyphBits;
  150.         streamRecord.info.font.name = nil;
  151.  
  152.         // DL 3/27/97:  Used to use the GX message, now we use the device method.        
  153.         status = psDevice->StreamFont(printerFont->theRealFont, &streamRecord);
  154.         nrequire(status, failed_StreamFont);
  155.  
  156.         printerFont->info |= fontIsEncoded;
  157.  
  158. failed_StreamFont:
  159.  
  160.         DisposePtr((Ptr)glyphBits);
  161.         
  162. failed_Alloc:
  163.  
  164.         return(status);
  165.         
  166.     }//FHDownloadEncoding
  167.  
  168.  
  169.  
  170. //<FF>
  171. /********************************************
  172.  
  173.     Function: FHDownloadFont:
  174.     
  175.     Function streams a font to the printer
  176.     based on printer font record specified.
  177.     Only the glyphs used by the printer font are 
  178.     downloaded.
  179.     
  180.     docDbase:                            Document font database. Used to retrieve variations from.
  181.     printerFont:                    Pointer to The printer font record.
  182.     legalTypes:                        Legal types for streaming.
  183.     productDescription:        Product description string.
  184.  
  185. *********************************************/
  186. OSErr FHDownloadFont(TFontHandlerPtr pFHRec, TPrinterFontRec *printerFont, scalerStreamTypeFlag legalTypes, char *productDescription)
  187.     {
  188.         OSErr                            status;
  189.         TFontDbase                docDbase = pFHRec->docDbase;
  190.         scalerStream            streamRecord;
  191.         unsigned char            name[256];
  192.         long                            nameLen;
  193.         unsigned long            *glyphBits;                    // Make copy of glyph bits because streaming can corrupt them.
  194.         gxFontVariation        *theVariations;
  195.         Boolean                        lockedDbase = false;
  196.         
  197.         /** Copy the glyph usage data **/
  198.         
  199.         status = PrNewPtr((Ptr *) &glyphBits, printerFont->usageSize);
  200.         nrequire(status, failed_Alloc);
  201.         memcpy(glyphBits, printerFont->glyphUsage, printerFont->usageSize);
  202.         
  203.         nameLen = FHGeneratePrinterName(printerFont, name);
  204.         check(nameLen);
  205.         
  206. #ifdef encodingsDontTakeFFFF
  207.         ResetSentinalValues(printerFont->printerFontCodes);
  208. #endif
  209.         streamRecord.types = legalTypes;
  210.         streamRecord.targetVersion = productDescription;
  211.         if (pFHRec->asciiDownload)
  212.             streamRecord.action = asciiDownloadStreamAction;
  213.         else
  214.             streamRecord.action = downloadStreamAction;
  215.         streamRecord.info.font.encoding = printerFont->printerFontCodes;
  216.         streamRecord.info.font.glyphBits = (long*)glyphBits;
  217.         streamRecord.info.font.name = (char*)name;
  218.         
  219.         /** Set up the variations fields in the stream record.  eMainBits implies don't need snapshots **/
  220.  
  221.         if (printerFont->dbIndex == eMainBits) {
  222.         
  223.             streamRecord.variationCount = selectAllVariations;
  224.             streamRecord.variations = nil;
  225.             
  226.         } else {
  227.             
  228.             status = FontDbaseLock(docDbase);
  229.             nrequire(status, failed_Lock);
  230.             
  231.             lockedDbase = true;
  232.             
  233.             status = FontDbaseGetGlyphBits(docDbase, printerFont->theRealFont, printerFont->dbIndex, nil, &theVariations);
  234.             nrequire(status, failed_GetVariations);
  235.             
  236.             streamRecord.variationCount = GXCountFontVariations(printerFont->theRealFont);
  237.             streamRecord.variations = theVariations;
  238.         
  239.         }//end if
  240.         
  241.         // DL 7/27/97:  Used to use gx message, now we use device method.
  242.         status = pFHRec->psDevice->StreamFont(printerFont->theRealFont, &streamRecord);
  243.         nrequire(status, failed_StreamFont);
  244.  
  245.         /* Mark font ready for use */
  246.         
  247.         printerFont->info |= (fontIsEncoded + fontIsDownloaded);
  248.  
  249. failed_StreamFont:
  250. failed_GetVariations:
  251.  
  252.         if (lockedDbase) {
  253.         
  254.             OSErr saveStatus = FontDbaseUnlock(docDbase);
  255.             if (status == noErr)
  256.                 status = saveStatus;
  257.             
  258.             ncheck(saveStatus);
  259.         
  260.         }//end if
  261.  
  262. failed_Lock:
  263.  
  264.         DisposePtr((Ptr)glyphBits);
  265.  
  266. failed_Alloc:
  267.         return(status);
  268.         
  269.     }//FHDownloadFont
  270.  
  271. //<FF>
  272. /********************************************
  273.     Function: FHDownloadFontAllDocGlyphs
  274.     
  275.     Function downloads the font specified by the encoding
  276.     in the printer font record.  The font will contain
  277.     all non-resident glyphs required by the document including
  278.     the ones encoded by this particular printer-font.  Thus
  279.     all subsequent printer fonts for the specified doc font
  280.     can just be re-encodings of this one thereby saving
  281.     memory.
  282.     
  283.     pFHRec:                pointer to font handler record.
  284.     printerFont:    The printer font specification.
  285.     
  286. **********************************************/
  287. OSErr FHDownloadFontAllDocGlyphs(TFontHandlerHdl hFHRec, TPrinterFontRec *printerFont);
  288. OSErr FHDownloadFontAllDocGlyphs(TFontHandlerHdl hFHRec, TPrinterFontRec *printerFont)
  289.     {
  290.         OSErr                                status;
  291.         long                                size;
  292.         register short            i;
  293.         scalerStream                streamRecord;
  294.         Handle                            h;
  295.         unsigned long                *docGlyphBits;
  296.         unsigned long                *docMinusPrinterBits;
  297.         unsigned long                *pNewBits, *pDocBits, *pResidentBits;
  298.         gxPrinterGlyphsRec    *fontLocation;                                            // A printer glyph location.
  299.         unsigned char                name[256];
  300.         long                                nameLen;
  301.         long                                nGlyphs;
  302.         gxFontVariation            *theVariations;
  303.         Boolean                            lockedDbase = false;
  304.  
  305.         nameLen = FHGeneratePrinterName(printerFont, name);
  306.         check(nameLen);
  307.         
  308.         /** Allocate space for a new bit array **/
  309.                 
  310.         size = printerFont->usageSize;                        // This is the right size for all glyph bits.
  311.     
  312.         /* Allocate a handle for the new bits and the Printer-Glyphs record. */
  313.         
  314.         status = FHSetWorkHandleSize(hFHRec, 2 * size + sizeof(gxPrinterGlyphsRec) - sizeof (unsigned long) , 1, &h);
  315.         nrequire(status, failed_SetSize);
  316.         
  317.         HLockHi(h);
  318.         docMinusPrinterBits = (unsigned long*)*h;
  319.         fontLocation = (gxPrinterGlyphsRec*)(*h + size);
  320.  
  321.         /** Get the bits used for the document **/
  322.         
  323.         nrequire(status = FontDbaseLock((*hFHRec)->docDbase), failed_Lock);
  324.         
  325.         status = FontDbaseGetFontInfo((*hFHRec)->docDbase, printerFont->theRealFont, &nGlyphs, nil, nil, nil);
  326.         nrequire(status, failed_GetInfo);
  327.         
  328.         status = FontDbaseGetGlyphBits((*hFHRec)->docDbase, printerFont->theRealFont, printerFont->dbIndex, &docGlyphBits, nil);
  329.         nrequire(status, failed_GetDocBits);
  330.         
  331.         /** Get the bits for resident glyphs **/
  332.         
  333.         memset(fontLocation->glyphBits, 0, size);        // clear it so message can set bits for glyph usage.
  334.         fontLocation->theFont = printerFont->theRealFont;
  335.         fontLocation->nGlyphs = nGlyphs;
  336.         status = (*hFHRec)->psDevice->GetPrinterGlyphsInformation(fontLocation);        // DL 7/27/97:  Used to use GX message.
  337.         nrequire(status, failed_GetFontGlyphs);
  338.         
  339.         /*** Compute a new bit array that is the document glyphs excluding the printer-resident glyphs ***/
  340.  
  341.         pDocBits = docGlyphBits;
  342.         pResidentBits = fontLocation->glyphBits;
  343.         pNewBits = docMinusPrinterBits;
  344.         for (i = (printerFont->usageSize / 4) - 1; i >= 0; --i)
  345.             *pNewBits++ = *pDocBits++ & ~*pResidentBits++;
  346.  
  347.  
  348.         /** Now Download the font **/
  349.         
  350. #ifdef encodingsDontTakeFFFF
  351.         ResetSentinalValues(printerFont->printerFontCodes);
  352. #endif
  353.         streamRecord.types = (*hFHRec)->legalStreamTypes;
  354.         streamRecord.targetVersion = (*hFHRec)->productDescription;
  355.         if ((*hFHRec)->asciiDownload)
  356.             streamRecord.action = asciiDownloadStreamAction;
  357.         else
  358.             streamRecord.action = downloadStreamAction;
  359.         streamRecord.info.font.encoding = printerFont->printerFontCodes;
  360.         streamRecord.info.font.name = (char*)name;
  361.         streamRecord.info.font.glyphBits = (long*)docMinusPrinterBits;
  362.  
  363.         /** Set up the variations fields in the stream record.  eMainBits implies don't need snapshots **/
  364.  
  365.         if (printerFont->dbIndex == eMainBits) {
  366.         
  367.             streamRecord.variationCount = selectAllVariations;
  368.             streamRecord.variations = nil;
  369.         
  370.         } else {
  371.         
  372.             status = FontDbaseGetGlyphBits((*hFHRec)->docDbase, printerFont->theRealFont,
  373.                                                                                 printerFont->dbIndex, nil, &theVariations);
  374.             nrequire(status, failed_GetVariations);
  375.             
  376.             streamRecord.variationCount = GXCountFontVariations(printerFont->theRealFont);
  377.             streamRecord.variations = theVariations;
  378.         
  379.         }//end if
  380.  
  381.         // DL 7/27/97: Used to use GX message, now we use device method.        
  382.         status = (*hFHRec)->psDevice->StreamFont(printerFont->theRealFont, &streamRecord);
  383.         nrequire(status, failed_Stream);
  384.  
  385.         /* Mark font as ready for use */
  386.         
  387.         printerFont->info |= (fontIsEncoded + fontIsDownloaded);
  388.                 
  389. failed_Stream:
  390. failed_GetVariations:
  391. failed_GetFontGlyphs:
  392. failed_GetDocBits:
  393. failed_GetInfo:
  394.  
  395.         {
  396.             register OSErr        saveStatus;
  397.             saveStatus = FontDbaseUnlock((*hFHRec)->docDbase);
  398.             ncheck(saveStatus);
  399.             if (saveStatus != noErr)
  400.                 status = saveStatus;
  401.         }
  402.  
  403. failed_Lock:
  404.  
  405.         FHReleaseWorkspace(hFHRec, 1);
  406.  
  407. failed_SetSize:
  408.     
  409.         return(status);    
  410.     
  411.     }//FHDownloadFontAllDocGlyphs
  412.  
  413.  
  414. //<FF>
  415. /********************************************
  416.  
  417.     Function: FHReEncodeFont
  418.     
  419.     Function generates a new font that is re-encoding
  420.     of another font that is either printer resident or
  421.     previously downloaded.
  422.     
  423.     pFHRec:                                Pointer to font handler handle (Handle assumed locked).
  424.     printerFont:                    The printer font to make encoding for.
  425.     printerFontToEncode:    Printer font record to re-encode.  If nil then re-encode the resident font.
  426.     
  427. *********************************************/
  428. OSErr FHReEncodeFont(TFontHandlerPtr pFHRec, TPrinterFontRec *printerFont, TPrinterFontRec *printerFontToEncode)
  429.     {
  430.         OSErr                                        status;
  431.         short                                        nameLen;
  432.         unsigned char                        name[256];
  433.         TRDParams                                rdParams;
  434.         
  435.         rdParams.rdMap = pFHRec->rdMap;
  436.         rdParams.resType = kScriptResType;
  437.         rdParams.resID = kFHScriptResID;
  438.         rdParams.rdFlags = eRDnoOptions;
  439.  
  440.         if (printerFont->info & fontCantBeRencoded) {
  441.                     
  442.             /************************
  443.                 Basically, do nothing, printer resident composite fonts cannot be reencoded
  444.                     but it is easier to let the main code that calls this routine
  445.                     not have to know the difference, since it is called to
  446.                     for printer-resident fonts.
  447.  
  448.                 Issue a "findfont" on this font since it may be a disk based font, we'd
  449.                 like to get it loaded into "fontdirectory" outside of the page save/restore
  450.                 because "findfont" can be really slow if the font dictionary is not in VM.
  451.                 
  452.                 Seems to only be problem on old NTX-J's but we'll do it all of the time
  453.                 becuase it is cheap enough to not special case.
  454.             *************************/
  455.             
  456.             nameLen = FHGetFontName(printerFont->theRealFont, printerFont->nameIndex, nil, nil, nil, nil, name);
  457.  
  458.             rdParams.resIndex = kFindFontPop;
  459.             nrequire(status = RDResPrintf(&rdParams, name, nameLen), failed_ResPrintf);
  460.  
  461.         } else {
  462.  
  463.     
  464.             /** Put name of encoded font on stack - this will be name to be used to get this encoding **/
  465.     
  466.             nameLen = FHGeneratePrinterName(printerFont, name);
  467.             rdParams.resIndex = kFontName;
  468.             nrequire(status = RDResPrintf(&rdParams, name, nameLen), failed_ResPrintf);
  469.             
  470.             /* Put the Boolean for fixing SEAC on the stack - only do for printer resident fonts */
  471.             
  472.             rdParams.resIndex = kBoolean;
  473.             if (printerFont->info & fontIsInPrinter)
  474.                 status = RDResPrintf(&rdParams, "true", 4);
  475.             else
  476.                 status = RDResPrintf(&rdParams, "false", 5);
  477.             nrequire(status, failed_ResPrintf);
  478.     
  479.             /* Stream the encoding vector onto the operand stack. */
  480.     
  481.             status = FHDownloadEncoding(pFHRec->psDevice, printerFont, pFHRec->legalStreamTypes, pFHRec->productDescription);
  482.             nrequire(status, failed_DownloadEncoding);
  483.     
  484.             /* Get the name of the font to re-encode on the operand stack */
  485.     
  486.             if (printerFontToEncode == nil)
  487.                 /* Put the PostScript name on the stack */
  488.                 nameLen = FHGetFontName(printerFont->theRealFont, printerFont->nameIndex, nil, nil, nil, nil, name);
  489.             else
  490.                 /* Put the name of printer-font at of the index specified on the stack */
  491.                 nameLen = FHGeneratePrinterName(printerFontToEncode, name);
  492.     
  493.             rdParams.resIndex = kFontName;                    
  494.             nrequire(status = RDResPrintf(&rdParams, name, nameLen), failed_ResPrintf);
  495.                     
  496.             /* Execute the procedure to make the encoded font */
  497.     
  498.             rdParams.resIndex = kReEncodeFont;
  499.             nrequire(status = RDResPrintf(&rdParams), failed_ResPrintf);
  500.             
  501.         }//end if
  502.         
  503.         printerFont->info |= fontIsEncoded;            // font on printer is ready to use.
  504.  
  505.  
  506. failed_ResPrintf:    
  507. failed_DownloadEncoding:
  508.  
  509.         return(status);
  510.         
  511.     }//FHReEncodeFont
  512.  
  513. //<FF>
  514. /********************************************
  515.  
  516.     Function: FHDoDocumentPermFonts
  517.     
  518.     Function makes all fonts that will be perminant
  519.     at the document level available on the printer.
  520.     For fonts with resident glyphs, a new encoding
  521.     is generated.  For non-resident fonts, they are
  522.     downloaded with the proper encoding.
  523.  
  524. **********************************************/
  525. OSErr FHDoDocumentPermFonts(TFontHandlerHdl hFHRec);
  526. OSErr FHDoDocumentPermFonts(TFontHandlerHdl hFHRec)
  527.     {
  528.         OSErr                                        status;
  529.         TFontHandlerPtr                    pFHRec;
  530.         TPrinterFontRec                    *printerFont, *printerFontToReEncode;
  531.         long                                        i, j, nPrFonts, nDocFonts;
  532.         TFontDbase                            fontDbase;
  533.         fhFont                                    theFont;
  534.         #if DEBUGLEVEL > 1
  535.             TRDParams        rdParams;
  536.             rdParams.rdMap = (*hFHRec)->rdMap;
  537.             rdParams.resType = kScriptResType;
  538.             rdParams.resID = kFHScriptResID;
  539.             rdParams.rdFlags = eRDnoOptions;
  540.         #endif
  541.         
  542.         HLockHi((Handle)hFHRec);                // Lock it so all of our glyph usage bits are locked 
  543.         pFHRec = *hFHRec;                                    // Because streaming could move memory.
  544.         
  545.         fontDbase = pFHRec->docDbase;
  546.                 
  547.         status = FontDbaseCountFonts(fontDbase, &nDocFonts);
  548.         nrequire(status, failed_CountFonts);
  549.         
  550.         nDocFonts = FHCountSnapshots(hFHRec);
  551.  
  552.         
  553.         /**********************************************
  554.             For each document font, download any encodings
  555.             for printer-resident glyphs, and download any
  556.             doc-level (permanent) printer-fonts and encodings
  557.         ***********************************************/
  558.         
  559.         for (i = 1; i <= nDocFonts; ++i) {
  560.         
  561.             status = FHGetIndexedSnapshot(hFHRec, i, &theFont);
  562.             nrequire(status, failed_GetFont);
  563.  
  564.             /** go through each printer font for the document font **/
  565.  
  566.             nPrFonts = FHCountPrinterFonts(hFHRec, theFont);            
  567.             for (j = 0; j < nPrFonts; ++j) {
  568.             
  569.                 status = FHGetIndexedPrinterFont(hFHRec, theFont, j, &printerFont, nil);
  570.                 nrequire(status, failed_GetPrinterFont);        
  571.                 
  572.                 /** Do the appropriate thing with the printer font **/
  573.                 
  574.                 if (printerFont->info & fontIsInPrinter) {
  575.                 
  576.                     /** Re-encode the printer-resident font **/
  577.                     
  578.                     status = FHReEncodeFont(pFHRec, printerFont, nil);
  579.                     nrequire(status, failed_ReEncodeResident);
  580.                     pFHRec->vmAvailable -= kEncodingOverhead;
  581.                     
  582.                     #if DEBUGLEVEL > 1
  583.                     rdParams.resIndex = kDebugShowVM;
  584.                     status = RDResPrintf(&rdParams, kEncodingOverhead);
  585.                     nrequire(status, failed_ResPrintf);                
  586.                     #endif
  587.                 
  588.                 } else if (printerFont->info & fontIsPerm) {
  589.                 
  590.                     if (printerFont->info & fontHasAllDocGlyphs) {
  591.  
  592.                         /******
  593.                             This Printer font will contain all downloaded glyphs with encoding it specifies,
  594.                             The reamining printer fonts for this doc font will just be re-encodings
  595.                         *******/
  596.                         
  597.                         printerFontToReEncode = printerFont;            // save reference for remaining printer-fonts.
  598.                         
  599.                         status = FHDownloadFontAllDocGlyphs(hFHRec, printerFont);
  600.                         nrequire(status, failed_AllGlyphs);
  601.                         pFHRec->vmAvailable -= printerFont->docVMUsage;
  602.                     
  603.                         #if DEBUGLEVEL > 1
  604.                         rdParams.resIndex = kDebugShowVM;
  605.                         status = RDResPrintf(&rdParams, printerFont->docVMUsage);
  606.                         nrequire(status, failed_ResPrintf);                
  607.                         #endif
  608.                         
  609.                     } else if (printerFont->info & fontIsEncodingOnly) {
  610.                     
  611.                         /** Make encoding for first printer font that has all document glyphs **/
  612.                         
  613.                         status = FHReEncodeFont(pFHRec, printerFont, printerFontToReEncode);
  614.                         nrequire(status, failed_ReEncodePrinterFont);
  615.                         pFHRec->vmAvailable -= kEncodingOverhead;
  616.                     
  617.                         #if DEBUGLEVEL > 1
  618.                         rdParams.resIndex = kDebugShowVM;
  619.                         status = RDResPrintf(&rdParams, kEncodingOverhead);
  620.                         nrequire(status, failed_ResPrintf);                
  621.                         #endif
  622.                     
  623.                     } else {
  624.                     
  625.                         /** Download the printer-font as an independant entity **/
  626.                         
  627.                         status = FHDownloadFont(pFHRec, printerFont, pFHRec->legalStreamTypes, pFHRec->productDescription);
  628.                         nrequire(status, failed_Download);
  629.                         pFHRec->vmAvailable -= printerFont->vmUsage;
  630.                     
  631.                         #if DEBUGLEVEL > 1
  632.                         rdParams.resIndex = kDebugShowVM;
  633.                         status = RDResPrintf(&rdParams, printerFont->vmUsage);
  634.                         nrequire(status, failed_ResPrintf);                
  635.                         #endif
  636.                     
  637.                     }//end if
  638.                                         
  639.                 }//end if
  640.                 
  641.  
  642.                 /** Output a PostScript comment to display the font reference **/
  643.                 #if DEBUGLEVEL > 1
  644.                 rdParams.resIndex = kDebugFontRef;
  645.                 status = RDResPrintf(&rdParams, &(printerFont->theRealFont), 4);
  646.                 nrequire(status, failed_ResPrintf);
  647.                 #endif
  648.             
  649.             }//end for
  650.             
  651.             /** Make a two-byte font if possible  for the document font **/
  652.                 
  653.             status = FHMakeTwoByteFont(hFHRec, theFont);
  654.             nrequire(status, failed_MakeTwoByte);
  655.     
  656.         }//end for
  657.  
  658.         #if DEBUGLEVEL > 1
  659.         rdParams.resIndex = kDebugShowVMTotal;
  660.         status = RDResPrintf(&rdParams, pFHRec->printerVM - pFHRec->vmAvailable);
  661.         nrequire(status, failed_ResPrintf);    
  662.         
  663.         rdParams.resIndex = kDebugShowVMLeft;
  664.         status = RDResPrintf(&rdParams, pFHRec->vmAvailable);
  665.         nrequire(status, failed_ResPrintf);
  666.         #endif
  667.  
  668. failed_MakeTwoByte:
  669. failed_ResPrintf:
  670. failed_Download:
  671. failed_ReEncodePrinterFont:
  672. failed_AllGlyphs:
  673. failed_ReEncodeResident:
  674. failed_GetPrinterFont:
  675. failed_GetFont:        
  676. failed_CountFonts:
  677.         
  678.         
  679.         HUnlock((Handle)hFHRec);
  680.         
  681.         return(status);
  682.             
  683.     }//FHDoDocumentPermFonts
  684.     
  685. /********************************************
  686.  
  687.     Function: FHDoPrerequisites
  688.     
  689.     Function computes and downloads necessary prerequisite
  690.     data for the fonts in the document.
  691.     
  692.     
  693. **********************************************/
  694. OSErr FHDoPrerequisites(TFontHandlerHdl hFHRec);
  695. OSErr FHDoPrerequisites(TFontHandlerHdl hFHRec)
  696.     {
  697.         OSErr                                        status;
  698.         TFontHandlerPtr                    pFHRec;
  699.         TFontDbase                            fontDbase;
  700.         long                                        prereqCount;            // Number of required prerequisites.
  701.         long                                        prereqVM;                    // This will be the total VM required by all prerequisites.
  702.         long                                        idx;
  703.         gxFont                                    theFont;                    // The font to pass into streaming.
  704.         unsigned char                        prereqData[256 + sizeof(scalerPrerequisiteItem)];        // name is pascal string.
  705.         scalerPrerequisiteItem    *prereqItem = (scalerPrerequisiteItem*)prereqData;    // point item at local data.
  706.         scalerStream                        streamRecord;
  707.         TRDParams                                rdParams;
  708.         
  709.         pFHRec = *hFHRec;
  710.         fontDbase = pFHRec->docDbase;
  711.  
  712.         streamRecord.types = pFHRec->legalStreamTypes;
  713.         streamRecord.targetVersion = pFHRec->productDescription;
  714.         streamRecord.action = prerequisiteItemStreamAction;
  715.         streamRecord.variationCount = 0;
  716.         streamRecord.variations = nil;
  717.         
  718.         rdParams.rdMap = pFHRec->rdMap;
  719.         rdParams.resType = kScriptResType;
  720.         rdParams.resID = kFHScriptResID;
  721.         rdParams.rdFlags = eRDnoOptions;
  722.  
  723.         
  724.         status = FontDbaseBuildPrerequisiteList(fontDbase, pFHRec->legalStreamTypes, 
  725.                                                                             pFHRec->productDescription, true, &prereqCount);
  726.         nrequire(status, failed_buildList);
  727.         
  728.         /*** Loop through the prerequisites and download them, updating avaialable VM ***/
  729.         
  730.         prereqVM = 0;
  731.         for (idx = 1; idx <= prereqCount; ++idx) {
  732.         
  733.             status = FontDbaseGetIndexedPrerequisite(fontDbase, idx, nil, &theFont, prereqItem);
  734.             nrequire(status, failed_GetPrereq);
  735.  
  736.             pFHRec = *hFHRec;
  737.             prereqVM += prereqItem->size;                                    // update amount used.
  738.             pFHRec->vmAvailable -= prereqItem->size;            // update amount available.
  739.             
  740.             /** Abort job if no printer memory is avilable **/
  741.             
  742.             require_action(pFHRec->vmAvailable > 0, failed_noRoomForItem, status = -9999;);
  743.             
  744.             /** Emit a %%BeginResource comment **/
  745.  
  746.             rdParams.resIndex = kBeginResource;
  747.             status = RDResPrintf(&rdParams, prereqItem->name);
  748.             nrequire(status, failed_beginResource);
  749.  
  750.             /** Stream the item **/
  751.             
  752.             streamRecord.info.prerequisiteItem = prereqItem->enumeration;            
  753.             status = (*hFHRec)->psDevice->StreamFont(theFont, &streamRecord);        // DL 7/27/97:  Used to use GX message.
  754.             nrequire(status, failed_stream);
  755.             
  756.             /** Emit a vm usage comment **/
  757.             
  758.             rdParams.resIndex = kDebugShowVM;
  759.             status = RDResPrintf(&rdParams, prereqItem->size);
  760.             nrequire(status, failed_vmComment);
  761.             
  762.             /** Emit an %%EndResource comment **/
  763.  
  764.             rdParams.resIndex = kEndResource;
  765.             status = RDResPrintf(&rdParams);
  766.             nrequire(status, failed_EndResource);
  767.                     
  768.         }//end for
  769.         
  770. failed_EndResource:
  771. failed_vmComment:
  772. failed_stream:
  773. failed_beginResource:
  774. failed_noRoomForItem:        
  775. failed_GetPrereq:
  776. failed_buildList:        
  777.         return(status);
  778.         
  779.     }//FHDoPrerequisites
  780.     
  781.     
  782.     
  783.  
  784. //<FF>
  785. /********************************************
  786.  
  787.     Function:    FontHandlerDoDocumentHeader
  788.     
  789.     This function outputs any necessary font
  790.     data for the document header. This inlucdes
  791.     all document fonts and encodings.
  792.     
  793. *********************************************/
  794. OSErr FontHandlerDoDocumentHeader(TFontHandlerContext context)
  795.     {
  796.         OSErr                    status;
  797.         TRDParams            rdParams;
  798.         
  799.         /** Only do anything if there are any fonts in the document **/
  800.         
  801.         if (FHCountSnapshots((TFontHandlerHdl)context) > 0) {
  802.  
  803.             /** Put font handler dictionary on the dictionary stack **/
  804.             
  805.             rdParams.rdMap = (*(TFontHandlerHdl)context)->rdMap;
  806.             rdParams.resType = kScriptResType;
  807.             rdParams.resID = kFHScriptResID;
  808.             rdParams.rdFlags = eRDnoOptions;
  809.             
  810.             rdParams.resIndex = kFHDictOnStack;
  811.             nrequire(status = RDResPrintf(&rdParams), failed_ResPrintf);
  812.             
  813.                 
  814.             /** Compute the doc-level (permanent) and page-level fonts **/
  815.             
  816.             status = FHFindDocLevelFonts((TFontHandlerHdl)context);
  817.             nrequire(status, failed_DocLevelFonts);
  818.             
  819.             /** Compute and download the required prerequisites **/
  820.             
  821.             status = FHDoPrerequisites((TFontHandlerHdl)context);
  822.             nrequire(status, failed_prerequisites);
  823.             
  824.             /** Download the document level fonts **/
  825.     
  826.             status = FHDoDocumentPermFonts((TFontHandlerHdl)context);
  827.             nrequire(status, failed_PermFonts);
  828.     
  829.             /** Take the font handler dictionary off the dictionary stack **/
  830.             
  831.             rdParams.resIndex = kFHDictOffStack;
  832.             nrequire(status = RDResPrintf(&rdParams), failed_ResPrintf2);
  833.             
  834.         } else {
  835.         
  836.             status = noErr;
  837.                         
  838.         }//end if
  839.         
  840.         
  841. failed_ResPrintf2:
  842. failed_PermFonts:
  843. failed_prerequisites:
  844. failed_DocLevelFonts:
  845. failed_ResPrintf:
  846.  
  847.  
  848.         return(status);
  849.     
  850.     }//FontHandlerDoDocumentHeader
  851.  
  852.